package com.yin.myproject.thread.listblock;

import com.yin.myproject.thread.spinlock.Lock;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Eason
 * @create 2018-03-08 11:52
 **/
public class MCSLock implements Lock {
    //原子变量指向队尾
    private AtomicReference<QNode> tail;
    //一个ThreadLocal指针来做链表,由QNode自身维护下一个节点的指针
    private ThreadLocal<QNode> myNode;


    public MCSLock() {
        this.tail = new AtomicReference<>();
        myNode = ThreadLocal.withInitial(() -> new QNode());
    }

    @Override
    public void lock() {
        QNode node = myNode.get();
        QNode preNode = tail.getAndSet(node);
        if (preNode != null) {
            node.lock = true;
            preNode.next = node;
            while (node.lock) {

            }
        }
    }

    @Override
    public void unlock() {
        QNode node = myNode.get();
        if (node.next == null) {
            //CAS操作,判断是否没有新加入的节点
            if (tail.compareAndSet(node, null)) {
                //没有新加入的节点,直接返回
                return;
            }
            //有新加入的节点,等待设置联关系
            while (node.next == null) {

            }
        }
        //通知下一节点获取锁
        node.next.lock = false;
        //设置nect节点为空,为下次锁清理状态
        node.next = null;
    }

    public static class QNode {
        volatile boolean lock;
        volatile QNode next;
    }


}
